﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MethodWorx.CMS.Content;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using MethodWorx.Core.DomainModel;
using MethodWorx.CMS.Workflow;
using MethodWorx.CMS.Membership;

namespace MethodWorx.CMS.Linq
{
    [Table(Name="dbo.Page")]
    public class LinqPage : Page, IPersistable
    {
        private EntitySet<LinqPage> proxyChildPages = new EntitySet<LinqPage>();
        private EntitySet<LinqContentItem> proxyChildContent = new EntitySet<LinqContentItem>();
        private EntitySet<LinqPublishedPlaceholder> proxyPublishedPlaceholders = new EntitySet<LinqPublishedPlaceholder>();
        private PageProperty[] properties;
        private WorkflowConfiguration[] workflows;
        private WorkflowConfiguration[] publishedWorkflows;
        private PageProperty[] publishedProperties;

        public LinqPage()
            : base((pt) => ((LinqPage)pt).ProxyChildPages.Where(p => p.Status != ContentStatus.Deleted),
                   (pt) => ((LinqPage)pt).proxyChildContent.Where(p => p.Status != ContentStatus.Deleted))
        {
        }
       
        #region Proxy Property For Id
        [Column(IsPrimaryKey=true, UpdateCheck=UpdateCheck.Never)]
        public new Guid Id { get { return base.Id; } set { base.Id = value; } }
        #endregion    
        #region Proxy Property For Name
        [Column(UpdateCheck=UpdateCheck.Never)]
        public new string Name { get { return base.Name; } set { base.Name = value; } }
        #endregion
        #region Proxy Property For Description
        [Column(UpdateCheck=UpdateCheck.Never)]
        public new string Description { get { return base.Description; } set { base.Description = value; } }
        #endregion
        #region Proxy Property For Parent

        private EntityRef<LinqPage> proxyParent = new EntityRef<LinqPage>();

        [Column(UpdateCheck=UpdateCheck.Never, CanBeNull=true)]
        public Guid? ParentId { get; set; }
        
        [Association(IsForeignKey=true, Name="Parent", OtherKey="Id", ThisKey="ParentId", Storage="proxyParent")]
        public LinqPage ProxyParent
        {
          get { return this.proxyParent.Entity; }
          // JS: Hack becuase linq to sql is setting this association to null
          //  for some reason
          set { if(value != null) this.proxyParent.Entity = value; }
        }
        
        public override Page  Parent
        {
          get { return this.ProxyParent; }
          // here we allow our proxy property to be set to null
          set { this.proxyParent.Entity = (LinqPage)value; }
        }
        #endregion
        #region Proxy Property For CreatedBy

        private EntityRef<LinqUser> proxyCreatedBy = new EntityRef<LinqUser>();

        [Column(UpdateCheck = UpdateCheck.Never, CanBeNull = true)]
        public Guid? CreatedById { get; set; }

        [Association(IsForeignKey = true, Name = "CreatedBy", OtherKey = "Id", ThisKey = "CreatedById", Storage = "proxyCreatedBy")]
        public LinqUser ProxyCreatedBy
        {
            get { return this.proxyCreatedBy.Entity; }
            // JS: Hack becuase linq to sql is setting this association to null
            //  for some reason
            set { if (value != null) this.proxyCreatedBy.Entity = value; }
        }

        public override User CreatedBy
        {
            get { return this.ProxyCreatedBy; }
            // here we allow our proxy property to be set to null
            set { this.proxyCreatedBy.Entity = (LinqUser)value; }
        }
        #endregion
        #region Proxy Property For Template
        private EntityRef<LinqPageTemplate> proxyTemplate = new EntityRef<LinqPageTemplate>();
        
        [Column(UpdateCheck=UpdateCheck.Never, CanBeNull=true)]
        public Guid? PageTemplateId { get; set; }
        
        [Association(IsForeignKey=true, Name="Template", OtherKey="Id", ThisKey="PageTemplateId", Storage="proxyTemplate")]
        public LinqPageTemplate ProxyTemplate
        {
          get { return this.proxyTemplate.Entity; }
          set { this.proxyTemplate.Entity = value; }
        }
        
        public override PageTemplate Template
        {
          get { return this.ProxyTemplate; }
            set { this.ProxyTemplate = (LinqPageTemplate)value; }
        }
        #endregion
        #region proxy property for child pages
        [Association(Name = "ChildPages", OtherKey = "ParentId", ThisKey = "Id", Storage = "proxyChildPages")]
        public EntitySet<LinqPage> ProxyChildPages
        {
            get { return this.proxyChildPages; }
            set { this.proxyChildPages.Assign(value); }
        }
        #endregion
        #region proxy property for child pages
        [Association(Name = "ChildContent", OtherKey = "PageId", ThisKey = "Id", Storage = "proxyChildContent")]
        public EntitySet<LinqContentItem> ProxyChildContent
        {
            get { return this.proxyChildContent; }
            set { this.proxyChildContent.Assign(value); }
        }
        #endregion
        
        #region Proxy Property For PublishedCss
        [Column(UpdateCheck=UpdateCheck.Never)]
        public new string PublishedCss { get { return base.PublishedCss; } set { base.PublishedCss = value; } }
        #endregion

        #region Proxy Property For PublishedScript
        [Column(UpdateCheck=UpdateCheck.Never)]
        public new string PublishedScript { get { return base.PublishedScript; } set { base.PublishedScript = value; } }
        #endregion
        #region proxy property for child pages
        [Association(Name = "PublishedPlaceholders", OtherKey = "PageId", ThisKey = "Id", Storage = "proxyPublishedPlaceholders")]
        public EntitySet<LinqPublishedPlaceholder> ProxyPublishedPlaceholders
        {
            get { return this.proxyPublishedPlaceholders; }
            set { this.proxyPublishedPlaceholders.Assign(value); }
        }
        #endregion
      
        
        #region Proxy Property For Tags
        [Column(UpdateCheck=UpdateCheck.Never)]
        public new string Tags { get { return base.Tags; } set { base.Tags = value; } }
        #endregion
      
        
        #region Proxy Property For PublishedTemplate
        [Column(UpdateCheck=UpdateCheck.Never)]
        public new string PublishedTemplate { get { return base.PublishedTemplate; } set { base.PublishedTemplate = value; } }
        #endregion
      
        [Column(UpdateCheck = UpdateCheck.Never, Name = "Properties")]
        public string PropertiesStorage { get; set; }

        [Column(UpdateCheck = UpdateCheck.Never, Name = "Workflows")]
        public string WorkflowStorage { get; set; }

        [Column(UpdateCheck = UpdateCheck.Never, Name = "PublishedWorkflows")]
        public string PublishedWorkflowStorage { get; set; }

        private Dictionary<string, string> publishedPlaceholders;
        public bool HavePublishedPlaceholdersBeenLoaded
        {
            get { return this.publishedPlaceholders != null; }
        }

        public override Dictionary<string, string> PublishedPlaceholders
        {
            get
            {
                if(this.publishedPlaceholders == null)
                {
                    this.publishedPlaceholders = new Dictionary<string, string>();
                    foreach(var pp in this.proxyPublishedPlaceholders)
                    {
                        this.publishedPlaceholders.Add(pp.Name, pp.Code);
                    }
                }
                return this.publishedPlaceholders;
            }
        }

        public override PageProperty [] Properties
        {
            get
            {
                if (this.properties == null)
                {
                    this.properties = (PageProperty[])this.PropertiesStorage.Base64DeserializeUsingXml() ?? new PageProperty[] { };
                }
                return this.properties;
            }
            set
            {
                this.properties = value;
                this.PropertiesStorage = this.properties.Base64SerializeUsingXml();
            }
        }

        public override WorkflowConfiguration[] Workflows
        {
            get
            {
                if (this.workflows == null)
                {
                    this.workflows = (WorkflowConfiguration[])this.WorkflowStorage.Base64DeserializeUsingXml(typeof(BranchStep), typeof(DefaultBranchStep)) ?? new WorkflowConfiguration[] { };
                }
                return this.workflows;
            }
            set
            {
                this.workflows = value;
                this.WorkflowStorage = this.workflows.Base64SerializeUsingXml(typeof(BranchStep), typeof(DefaultBranchStep));
            }
        }

        public override WorkflowConfiguration[] PublishedWorkflows
        {
            get
            {
                if (this.publishedWorkflows == null)
                {
                    this.publishedWorkflows = (WorkflowConfiguration[])this.PublishedWorkflowStorage.Base64DeserializeUsingXml(typeof(BranchStep), typeof(DefaultBranchStep)) ?? new WorkflowConfiguration[] { };
                }
                return this.publishedWorkflows;
            }
            set
            {
                this.publishedWorkflows = value;
                this.PublishedWorkflowStorage = this.publishedWorkflows.Base64SerializeUsingXml(typeof(BranchStep), typeof(DefaultBranchStep));
            }
        }


        [Column(UpdateCheck = UpdateCheck.Never, Name = "PublishedProperties")]
        public string PublishedPropertiesStorage { get; set; }

        public override PageProperty[] PublishedProperties
        {
            get
            {
                if (this.publishedProperties == null)
                {
                    this.publishedProperties = (PageProperty[])this.PublishedPropertiesStorage.Base64DeserializeUsingXml() ?? new PageProperty[] { };
                }
                return this.publishedProperties;
            }
            set
            {
                this.publishedProperties = value;
                this.PublishedPropertiesStorage = this.publishedProperties.Base64SerializeUsingXml();
            }
        }

        
        #region Proxy Property For DateCreated
        [Column(UpdateCheck=UpdateCheck.Never)]
        public new DateTime DateCreated { get { return base.DateCreated; } set { base.DateCreated = value; } }
        #endregion
        
        #region Proxy Property For DatePublished
        [Column(UpdateCheck=UpdateCheck.Never)]
        public new DateTime? DatePublished { get { return base.DatePublished; } set { base.DatePublished = value; } }
        #endregion

        
        #region Proxy Property For Status
        [Column(UpdateCheck=UpdateCheck.Never)]
        public new ContentStatus Status { get { return base.Status; } set { base.Status = value; } }
        #endregion
      
      
      
    }
}
